﻿///////////////////////////////////////////////////
/// toto Code
/// $Id: thread.cc 2 2009-12-14 12:41:06Z tonyjobmails $
/// $Date: 2009-12-14 20:41:06 +0800 (一, 14 12月 2009) $
/// $Author: tonyjobmails $
/// $Revision: 2 $
/// E-mail: tonyjobmails@gmail.com
/// filename: thread.cc
/// function: 线程基类的定义
///////////////////////////////////////////////////

#include <iostream>
#include <signal.h>
#include "CThread.h"

///////////////////
/// @brief 线程开始
/// @return 成功与否
bool CThread::start()
{
	if(this->isAlive())
	{
		/// 线程已创建
#ifdef _TOTO_DEBUG
		std::cout << "[线程开启]线程(" << this->name << ")已开启" << std::endl;
#endif
		return true;
	}

	pthread_attr_t attr;
	pthread_attr_init(&attr);
	if(this->isJoinable())
		::pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	if(::pthread_create(&this->thread, &attr, CThread::threadFunc, this) != 0)
	{
#ifdef _TOTO_DEBUG
		std::cout << "[线程创建]线程(" << this->name << ")创建失败" << std::endl;
#endif
		return false;
	}
	::pthread_attr_destroy(&attr);
	this->mutex.lock();
	if(!this->isAlive())
		this->cond.wait(this->mutex);
	this->mutex.unlock();

	return true;
}

///////////////////
/// @brief 线程方法
/// @param arg：参数
/// @return 指针
void* CThread::threadFunc(void *arg)
{
	CThread *thread = (CThread *)arg;

	thread->mutex.lock();
	thread->state = THREAD_STATE_ALIVE;
	thread->cond.broadcast();
	thread->mutex.unlock();

	/// 阻塞所有信号
	sigset_t sig_mask;
	::sigfillset(&sig_mask);
	::pthread_sigmask(SIG_SETMASK, &sig_mask, NULL);

	/// 线程主调函数
	thread->run();

	thread->mutex.lock();
	/// 线程结束
	thread->end();
	thread->cond.broadcast();
	thread->mutex.unlock();

	if(!thread->isJoinable())
	{
		thread->mutex.lock();
		if(thread->isAlive())
			thread->cond.wait(thread->mutex);
		thread->mutex.unlock();
		delete thread;
		thread = NULL;
	}

	return thread;
}

///////////////////
/// @brief 等待线程结束
void CThread::join()
{
	if(this->thread && joinable)
	{
		this->mutex.lock();
		if(this->isAlive())
			this->cond.wait(this->mutex);
		this->mutex.unlock();
		::pthread_join(this->thread, NULL);
		this->thread = 0;
	}
}

